﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ExchangeCurrencyRate.Entity;

namespace ExchangeCurrencyRate
{
    public sealed class CurrencyRateManager
    {
        private CurrencyRateProvider currencyRateProvider = CurrencyRateProvider.GetProvider();

        /// <summary>
        /// Get currency exchange rate
        /// </summary>
        /// <param name="fromCurrencyCode">First currency code</param>
        /// <param name="toCurrencyCode">Second currency code</param>
        /// <returns>Return <see cref="ExchangeCurrencyRate.Entity.ExchangeRate"/></returns>
        public ExchangeRate GetExchangeRate(string fromCurrencyCode, string toCurrencyCode)
        {
            return GetExchangeRate(fromCurrencyCode, toCurrencyCode, DateTime.Now);
        }
        /// <summary>
        /// Get currency exchange rate for date
        /// </summary>
        /// <param name="fromCurrencyCode">First currency code</param>
        /// <param name="toCurrencyCode">Second currency code</param>
        /// <param name="dateTime"><see cref="System.DateTime"/></param>
        /// <returns>Return <see cref="ExchangeCurrencyRate.Entity.ExchangeRate"/></returns>
        public ExchangeRate GetExchangeRate(string fromCurrencyCode, string toCurrencyCode, DateTime dateTime)
        {
            if (!this.CheckCurrencyCode(fromCurrencyCode))
            {
                throw new ArgumentException("Invalid Currency Code", "fromCurrencyCode");
            }
            else if (!this.CheckCurrencyCode(toCurrencyCode))
            {
                throw new ArgumentException("Invalid Currency Code", "toCurrencyCode");
            }
            return currencyRateProvider.GetExchangeRate(fromCurrencyCode, toCurrencyCode, dateTime);
        }
        /// <summary>
        /// Checks if currency code is valid.
        /// </summary>
        /// <param name="currencyCode">Currency code</param>
        /// <returns>True if valid, False otherwise</returns>
        public bool CheckCurrencyCode(string currencyCode)
        {
            return currencyRateProvider.CheckCurrencyCode(currencyCode);
        }
        /// <summary>
        /// Exchange <see cref="value"/> from <see cref="fromCurrencyCode"/> to <see cref="toCurrencyCode"/> for <see cref="dateTime"/>.
        /// </summary>
        /// <param name="fromCurrencyCode">First currency code</param>
        /// <param name="toCurrencyCode">Second currency code</param>
        /// <param name="dateTime">Given <see cref="System.DateTime"/></param>
        /// <param name="value">Money amount</param>
        /// <returns>Money amount in <see cref="toCurrencyCode"/></returns>
        public decimal Exchange(string fromCurrencyCode, string toCurrencyCode, DateTime dateTime, decimal value)
        {
            return Exchange(GetExchangeRate(fromCurrencyCode, toCurrencyCode, dateTime), value);
        }
        /// <summary>
        /// Exchange <see cref="value"/> from <see cref="fromCurrencyCode"/> to <see cref="toCurrencyCode"/>.
        /// </summary>
        /// <param name="fromCurrencyCode">First currency code</param>
        /// <param name="toCurrencyCode">Second currency code</param>
        /// <param name="value">Money amount</param>
        /// <returns>Money amount in <see cref="toCurrencyCode"/></returns>
        public decimal Exchange(string fromCurrencyCode, string toCurrencyCode, decimal value)
        {
            if (fromCurrencyCode.Equals(toCurrencyCode))
            {
                return value;
            }
            return Exchange(GetExchangeRate(fromCurrencyCode, toCurrencyCode), value);
        }
        /// <summary>
        /// Exchange money for given <see cref="ExchangeCurrencyRate.Entity.ExchangeRate"/>.
        /// </summary>
        /// <param name="exchangeRate">Exchange rate</param>
        /// <param name="value">Money amount</param>
        /// <returns>Returns money amount in other currency</returns>
        public decimal Exchange(ExchangeRate exchangeRate, decimal value)
        {
            if (null == exchangeRate)
            {
                throw new ArgumentNullException("exchangeRate");
            }
            return value * exchangeRate.Rate;
        }
    }
}
